/*-------------------------------------------------------------------------
 *
 * hba.h
 *	  hba.c 的接口
 *
 *
 * src/include/libpq/hba.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef HBA_H
#define HBA_H

#include "libpq/pqcomm.h"	/* pgrminclude 忽略 */	/* NetBSD 所需 */
#include "nodes/pg_list.h"
#include "regex/regex.h"


/*
 * 以下枚举表示 PostgreSQL 支持的身份验证方法。
 *
 * 注意：确保与 hba.c 中的 UserAuthName 数组保持同步。
 */
typedef enum UserAuth
{
	uaReject,
	uaImplicitReject,			/* 不是用户可见的选项 */
	uaTrust,
	uaIdent,
	uaPassword,
	uaMD5,
#ifdef FDDGM
	uaSM3,
#endif
	uaSCRAM,
	uaGSS,
	uaSSPI,
	uaPAM,
	uaBSD,
	uaLDAP,
	uaCert,
	uaRADIUS,
	uaPeer
#define USER_AUTH_LAST uaPeer	/* 必须是此枚举的最后一个值 */
} UserAuth;

/*
 * 表示 pg_hba.conf 条目的数据结构
 */

typedef enum IPCompareMethod
{
	ipCmpMask,
	ipCmpSameHost,
	ipCmpSameNet,
	ipCmpAll
} IPCompareMethod;

typedef enum ConnType
{
	ctLocal,
	ctHost,
	ctHostSSL,
	ctHostNoSSL,
	ctHostGSS,
	ctHostNoGSS,
} ConnType;

typedef enum ClientCertMode
{
	clientCertOff,
	clientCertCA,
	clientCertFull
} ClientCertMode;

typedef enum ClientCertName
{
	clientCertCN,
	clientCertDN
} ClientCertName;

typedef struct HbaLine
{
	int			linenumber;
	char	   *rawline;
	ConnType	conntype;
	List	   *databases;
	List	   *roles;
	struct sockaddr_storage addr;
	int			addrlen;		/* 如果没有有效的地址则为零 */
	struct sockaddr_storage mask;
	int			masklen;		/* 如果没有有效的掩码则为零 */
	IPCompareMethod ip_cmp_method;
	char	   *hostname;
	UserAuth	auth_method;
	char	   *usermap;
	char	   *pamservice;
	bool		pam_use_hostname;
	bool		ldaptls;
	char	   *ldapscheme;
	char	   *ldapserver;
	int			ldapport;
	char	   *ldapbinddn;
	char	   *ldapbindpasswd;
	char	   *ldapsearchattribute;
	char	   *ldapsearchfilter;
	char	   *ldapbasedn;
	int			ldapscope;
	char	   *ldapprefix;
	char	   *ldapsuffix;
	ClientCertMode clientcert;
	ClientCertName clientcertname;
	char	   *krb_realm;
	bool		include_realm;
	bool		compat_realm;
	bool		upn_username;
	List	   *radiusservers;
	char	   *radiusservers_s;
	List	   *radiussecrets;
	char	   *radiussecrets_s;
	List	   *radiusidentifiers;
	char	   *radiusidentifiers_s;
	List	   *radiusports;
	char	   *radiusports_s;
} HbaLine;

typedef struct IdentLine
{
	int			linenumber;

	char	   *usermap;
	char	   *ident_user;
	char	   *pg_role;
	regex_t		re;
} IdentLine;

/*
 * 从身份验证配置文件（pg_ident.conf 或 pg_hba.conf）中词法分析得到的单个字符串令牌，
 * 以及令牌是否被引用的信息。
 */
typedef struct AuthToken
{
	char	   *string;
	bool		quoted;
} AuthToken;

/*
 * TokenizedAuthLine 表示从身份验证配置文件中词法分析得到的一行。
 * "fields" 列表中的每个项目都是 AuthTokens 的子列表。
 * 对于空行或全注释行，我们不会发出 TokenizedAuthLine，因此 "fields" 永远不会是 NIL（其子列表也不会）。
 *
 * 异常：如果在词法分析过程中发生错误，fields 可能为 NIL，此时 err_msg != NULL。
 */
typedef struct TokenizedAuthLine
{
	List	   *fields;			/* AuthTokens 列表的列表 */
	int			line_num;		/* 行号 */
	char	   *raw_line;		/* 原始行文本 */
	char	   *err_msg;		/* 如有错误消息 */
} TokenizedAuthLine;

/* 避免在此处包含 libpq/libpq-be.h 的补丁 */
typedef struct Port hbaPort;

extern bool load_hba(void);
extern bool load_ident(void);
extern const char *hba_authname(UserAuth auth_method);
extern void hba_getauthmethod(hbaPort *port);
extern int	check_usermap(const char *usermap_name,
						  const char *pg_role, const char *auth_user,
						  bool case_insensitive);
extern HbaLine *parse_hba_line(TokenizedAuthLine *tok_line, int elevel);
extern IdentLine *parse_ident_line(TokenizedAuthLine *tok_line, int elevel);
extern bool pg_isblank(const char c);
extern MemoryContext tokenize_auth_file(const char *filename, FILE *file,
										List **tok_lines, int elevel);

#endif							/* HBA_H */
